package com.yilin.tms.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import com.google.gson.internal.LinkedTreeMap;
import com.google.gson.reflect.TypeToken;
import com.yilin.commons.exception.BusinessException;
import com.yilin.commons.util.CommonUtil;
import com.yilin.commons.util.HttpService;
import com.yilin.commons.util.JsonUtil;
import com.yilin.tms.core.application.PageData;
import com.yilin.tms.core.commons.utils.QueryUtil;
import com.yilin.tms.core.entity.capital.QueryBankInfo;
import com.yilin.tms.core.entity.system.param.*;
import com.yilin.tms.system.mapper.*;
import com.yilin.tms.system.service.IParamService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;


@Service
@Transactional
public class ParamService extends ServiceImpl<BankCodeMapper, BankCode> implements IParamService {

    //阿里 银行卡信息获取接口
    private static final String queryBankInfoUrl = "https://ccdcapi.alipay.com/validateAndCacheCardInfo.json";
    @Resource
    AreaMapper areaDao;
    @Resource
    BankMapper bankDao;
    @Resource
    BankCodeMapper bankCodeDao;
    @Resource
    CityMapper cityDao;
    @Resource
    GoodsTypeMapper goodsTypeDao;
    @Resource
    TransportTypeMapper transportTypeDao;
    @Resource
    TruckEnergyTypeMapper truckEnergyTypeDao;
    @Resource
    TruckPlateMapper truckPlateDao;
    @Resource
    CommTruckTypeMapper commTruckTypeDao;
    @Resource
    TruckTypeMapper truckTypeDao;

    //#################################################【前台列表区】############################################################

    @Override
    public List<Area> getAreaPage(Area area) {
        if (area.getSort() == null) area.setSort("id-ASC");
        return areaDao.selectList(QueryUtil.andQueryWrapper(new QueryWrapper<>(), area));
    }

    @Override
    public PageData<Bank> getBankPage(Bank bank, int i, Integer limit) {
        if (bank.getSort() == null) bank.setSort("id-ASC");
        return bankDao.selectPage(new PageData<>(i, limit), QueryUtil.andQueryWrapper(new QueryWrapper<>(), bank));
    }

    @Override
    public PageData<BankCode> getBankCodePage(BankCode bankCode, int i, Integer limit) {
        if (bankCode.getSort() == null) bankCode.setSort("id-ASC");
        return bankCodeDao.selectPage(new PageData<>(i, limit), QueryUtil.andQueryWrapper(new QueryWrapper<>(), bankCode));
    }

    @Override
    public PageData<City> getCityPage(City city, int i, Integer limit) {
        if (city.getSort() == null) city.setSort("id-ASC");
        return cityDao.selectPage(new PageData<>(i, limit), QueryUtil.andQueryWrapper(new QueryWrapper<>(), city));
    }

    @Override
    public List<GoodsType> getTreeGoodsTypeList(GoodsType goodsType) {
        if (goodsType.getSort() == null) goodsType.setSort("id-ASC");
        return goodsTypeDao.selectList(QueryUtil.andQueryWrapper(new QueryWrapper<>(), goodsType));
    }

    @Override
    public GoodsType getGoodsTypeById(String goodsTypeId) {
        return goodsTypeDao.selectById(goodsTypeId);
    }

    @Override
    public List<TransportType> getTransportTypeList(TransportType transportType) {
        if (transportType.getSort() == null) transportType.setSort("id-ASC");
        return transportTypeDao.selectList(QueryUtil.andQueryWrapper(new QueryWrapper<>(), transportType));
    }

    @Override
    public List<TruckEnergyType> getTruckEnergyTypeList(TruckEnergyType truckEnergyType) {
        if (truckEnergyType.getSort() == null) truckEnergyType.setSort("id-ASC");
        return truckEnergyTypeDao.selectList(QueryUtil.andQueryWrapper(new QueryWrapper<>(), truckEnergyType));
    }

    @Override
    public List<TruckPlate> getTruckPlateList(TruckPlate truckPlate) {
        if (truckPlate.getSort() == null) truckPlate.setSort("id-ASC");
        return truckPlateDao.selectList(QueryUtil.andQueryWrapper(new QueryWrapper<>(), truckPlate));
    }

    @Override
    public List<TruckType> getTreeTruckTypeList(TruckType truckType) {
        if (truckType.getSort() == null) truckType.setSort("id-ASC");
        return truckTypeDao.selectList(QueryUtil.andQueryWrapper(new QueryWrapper<>(), truckType));
    }

    //#################################################【编辑区】############################################################

    @Override
    public void editArea(Area area) {
        if (area.getId() == null) {
            area.setCreateTime(new Date());
            areaDao.insert(area);
        } else {
            area.setUpdateTime(new Date());
            areaDao.updateById(area);
        }

    }

    @Override
    public void editBank(Bank bank) {
        if (bank.getId() == null) {
            bank.setCreateTime(new Date());
            bankDao.insert(bank);
        } else {
            bank.setUpdateTime(new Date());
            bankDao.updateById(bank);
        }
    }

    @Override
    public void editBankCode(BankCode bankCode) {
        if (bankCode.getId() == null) {
            bankCode.setCreateTime(new Date());
            bankCodeDao.insert(bankCode);
        } else {
            bankCode.setUpdateTime(new Date());
            bankCodeDao.updateById(bankCode);
        }
    }

    @Override
    public void editCity(City city) {
        if (city.getId() == null) {
            city.setCreateTime(new Date());
            cityDao.insert(city);
        } else {
            city.setUpdateTime(new Date());
            cityDao.updateById(city);
        }
    }

    @Override
    public void editGoodsType(GoodsType goodsType) {
        if (goodsType.getId() == null) {
            goodsType.setCreateTime(new Date());
            goodsTypeDao.insert(goodsType);
        } else {
            goodsType.setUpdateTime(new Date());
            goodsTypeDao.updateById(goodsType);
        }
    }

    @Override
    public void editTransportType(TransportType transportType) {
        if (transportType.getId() == null) {
            transportType.setCreateTime(new Date());
            transportTypeDao.insert(transportType);
        } else {
            transportType.setUpdateTime(new Date());
            transportTypeDao.updateById(transportType);
        }
    }

    @Override
    public void editTruckEnergyType(TruckEnergyType truckEnergyType) {
        if (truckEnergyType.getId() == null) {
            truckEnergyType.setCreateTime(new Date());
            truckEnergyTypeDao.insert(truckEnergyType);
        } else {
            truckEnergyType.setUpdateTime(new Date());
            truckEnergyTypeDao.updateById(truckEnergyType);
        }
    }

    @Override
    public void editTruckPlate(TruckPlate truckPlate) {
        if (truckPlate.getId() == null) {
            truckPlate.setCreateTime(new Date());
            truckPlateDao.insert(truckPlate);
        } else {
            truckPlate.setUpdateTime(new Date());
            truckPlateDao.updateById(truckPlate);
        }
    }

    @Override
    public void editTruckType(TruckType truckType) {
        if (truckType.getId() == null) {
            truckType.setCreateTime(new Date());
            truckTypeDao.insert(truckType);
        } else {
            truckType.setUpdateTime(new Date());
            truckTypeDao.updateById(truckType);
        }
    }

    @Override
    public void editCommTruckType(CommTruckType truckType) {
        if (truckType.getId() == null) {
            truckType.setCreateTime(new Date());
            commTruckTypeDao.insert(truckType);
        } else {
            truckType.setUpdateTime(new Date());
            commTruckTypeDao.updateById(truckType);
        }
    }

    //#################################################【删除区】############################################################

    @Override
    public void deleteArea(Area area) {
        areaDao.deleteById(area);
    }

    @Override
    public void deleteBank(Bank bank) {
        bankDao.deleteById(bank);
    }

    @Override
    public void deleteBankCode(BankCode bankCode) {
        bankCodeDao.deleteById(bankCode);
    }

    @Override
    public void deleteCity(City city) {
        cityDao.deleteById(city);
    }

    @Override
    public void deleteGoodsType(GoodsType goodsType) {
        goodsTypeDao.deleteById(goodsType);
    }

    @Override
    public void deleteTransportType(TransportType transportType) {
        transportTypeDao.deleteById(transportType);
    }

    @Override
    public void deleteTruckEnergyType(TruckEnergyType truckEnergyType) {
        truckEnergyTypeDao.deleteById(truckEnergyType);
    }

    @Override
    public void deleteTruckPlate(TruckPlate truckPlate) {
        truckPlateDao.deleteById(truckPlate);
    }

    @Override
    public void deleteTruckType(TruckType truckType) {
        truckTypeDao.deleteById(truckType);
    }

    @Override
    public void deleteCommTruckType(CommTruckType truckType) {
        commTruckTypeDao.deleteById(truckType);
    }


    //#################################################【列表检索】############################################################

    @Override
    public List<City> getCityList(String cityName) {
        QueryWrapper<City> queryWrapper = new QueryWrapper<>();
        if (cityName != null) queryWrapper.like("city_name", cityName);
        return cityDao.selectList(queryWrapper);
    }

    @Override
    public List<Bank> getBankList(String bankName) {
        QueryWrapper<Bank> queryWrapper = new QueryWrapper<>();
        if (bankName != null) queryWrapper.like("cn_name", bankName);
        return bankDao.selectList(queryWrapper);
    }

    @Override
    public List<TruckType> getTruckTypeList(TruckType.IsTrailer isTrailer) {
        return truckTypeDao.selectList(new QueryWrapper<TruckType>().eq("is_trailer", isTrailer));
    }

    @Override
    public List<TruckEnergyType> getTruckEnergyTypeList() {
        return truckEnergyTypeDao.selectList(new QueryWrapper<>());
    }

    @Override
    public List<TruckPlate> getTruckPlateList() {
        return truckPlateDao.selectList(new QueryWrapper<>());
    }

    @Override
    public List<CommTruckType> getCommTruckTypeList(TruckType.IsTrailer isTrailer) {
        return commTruckTypeDao.selectList(new QueryWrapper<CommTruckType>().eq("isTrailer", isTrailer));
    }

    @Override
    public List<CommTruckType> getTruckTypeListByLevel(Integer leven) {
        return commTruckTypeDao.selectList(new QueryWrapper<CommTruckType>().eq("type_level", leven));
    }

    @Override
    public List<CommTruckType> getTruckTypeListByParent(String parentTruckType) {
        return commTruckTypeDao.selectList(new QueryWrapper<CommTruckType>().eq("parent_id", parentTruckType));
    }

    //根据ID数组获取公共车辆类型
    @Override
    public List<CommTruckType> getCommTruckTypeListByIds(String[] commTruckTypeIds) {
        return commTruckTypeDao.selectBatchIds(Arrays.asList(commTruckTypeIds));
    }

    //根据code获取货物类型
    @Override
    public List<GoodsType> getGoodsTypeByCode(String goodsTypeCode) {
        return goodsTypeDao.selectList(new QueryWrapper<GoodsType>().eq("code", goodsTypeCode));
    }


    @Override
    public List<CommTruckType> getCommTruckTypeList(CommTruckType commTruckType) {
        return commTruckTypeDao.selectList(QueryUtil.andQueryWrapper(new QueryWrapper<>(), commTruckType));
    }

    @Override
    public List<CommTruckType> getPricingCommTruckTypeList() {
        QueryWrapper<CommTruckType> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id", "0");
        queryWrapper.eq("is_trailer", false);
        return commTruckTypeDao.selectList(queryWrapper);
    }

    //通过车辆名称检索车辆类型
    @Override
    public List<TruckType> queryTruckTypeByName(String name) {
        return truckTypeDao.selectList(new QueryWrapper<TruckType>().eq("name", name));
    }

    @Override
    public PageData<BankCode> queryBankCodePage(String bankShortName, String cityName, String bankName, int i, Integer limit) {
        QueryWrapper<BankCode> queryWrapper = new QueryWrapper<>();
        if (bankShortName != null) queryWrapper.eq("bank_short_name", bankShortName);
        if (cityName != null) queryWrapper.eq("city", cityName);
        if (bankName != null) queryWrapper.like("bank_branch_name", bankName);
        return bankCodeDao.selectPage(new PageData<>(i, limit), queryWrapper);
    }

    //#################################################【单条检索】############################################################

    @Override
    public TruckEnergyType getTruckEnergyTypeByName(String name) {
        return truckEnergyTypeDao.selectOne(new QueryWrapper<TruckEnergyType>().eq("name", name));
    }

    @Override
    public TruckType getTruckTypeById(String TruckTypeId) {
        return truckTypeDao.selectOne(new QueryWrapper<TruckType>().eq("id", TruckTypeId));
    }

    @Override
    public TruckPlate getTruckPlateById(String id) {
        return truckPlateDao.selectOne(new QueryWrapper<TruckPlate>().eq("id", id));
    }

    //根据车辆id获取车辆 添加人：yhp 添加时间：2022年6月23日10:59:05
    @Override
    public CommTruckType getCommTruckTypeById(String vehicleId) {
        return commTruckTypeDao.selectById(vehicleId);
    }


    //通过能源名称检索能源类型
    @Override
    public TruckEnergyType queryTruckEnergyTypeByName(String name) {
        return truckEnergyTypeDao.selectOne(new QueryWrapper<TruckEnergyType>().eq("name", name));
    }

    // 通过卡号获取银行卡信息
    @Override
    public Bank getBankcardInfo(String bankNo) {
        String bankUrl = String.format("%s?_input_charset=utf-8&cardNo=%s&cardBinCheck=true", queryBankInfoUrl, bankNo);
        String json = HttpService.pubPost("", bankUrl, "UTF-8");
        QueryBankInfo queryBankInfo = new Gson().fromJson(json, QueryBankInfo.class);
        if (queryBankInfo.getValidated()) {
            Bank bank = getBankByCode(queryBankInfo.getBank());
            if (bank == null) throw new BusinessException("暂时不支持该银行卡（暂时不支持部分地方银行、农村信用社等等）");
            return bank;
        }
        throw new BusinessException("未检索到银行，请手动选择银行");
    }

    //通过车牌名称获取车牌类型
    @Override
    public TruckPlate queryTruckPlateByName(String name) {
        return truckPlateDao.selectOne(new QueryWrapper<TruckPlate>().eq("name", name));
    }

    @Override
    public TransportType getTransportTypeByCode(String code) {
        QueryWrapper<TransportType> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("code", code);
        return transportTypeDao.selectOne(queryWrapper);
    }

    @Override
    public TruckEnergyType getTruckEnergyById(String truckEnergyTypeId) {
        return truckEnergyTypeDao.selectById(truckEnergyTypeId);
    }

    @Override
    public Bank getBankByCode(String code) {
        QueryWrapper<Bank> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("short_name", code);
        return bankDao.selectOne(queryWrapper);
    }

    /**
     * 为银行联行号添加银行简称 该方法请谨慎调用!!!
     */
    @Deprecated
    private void setBankShortName() {
        try {
            ArrayList<BankCode> bankCodes = new ArrayList<>(180000);
            //获取银行名称
            List<Bank> bankList = bankDao.selectList(new QueryWrapper<>());
            //根据银行名称获取联行号对象
            for (Bank bank : bankList) {
                QueryWrapper<BankCode> wrapper = new QueryWrapper<>();
                wrapper.like("bank_branch_name", bank.getCnName()).isNull("bank_short_name");
                List<BankCode> bankCodeList = list(wrapper);
                //联行号存入银行缩写
                for (BankCode bankCode : bankCodeList) {
                    bankCode.setBankShortName(bank.getShortName());
                }
                bankCodes.addAll(bankCodeList);
            }
            bankCodes.trimToSize();
            //更新联行号数据
            updateBatchById(bankCodes);
        } catch (RuntimeException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 生成银行联行号表 该方法请谨慎调用！！！！！
     */
    @Deprecated
    private void generateBankInterbankNumber() {
        //获取省份数据
        HashMap<String, String> provinceMap = getProvinceMap();
        //获取城市数据
        HashMap<String, City> cityMap = getCityMap();
        //获取联行号表格数据
        ArrayList<LinkedTreeMap<String, Object>> webTableList = new ArrayList<>(180000);
        for (int i = 1; i < 20; i++) {
            Map<String, String> param = new HashMap<>();
            param.put("current", String.valueOf(i));
            param.put("size", "10000");
            String json = HttpService.doPost("http://lianhanghao.com/api/bank/lhhTableData", param);
            Map<String, Object> stringObjectMap = JsonUtil.jsonToObject(json, new TypeToken<Map<String, Object>>() {
            });
            Map<String, Object> dataMap = CommonUtil.cast(stringObjectMap.get("data"));
            ArrayList<LinkedTreeMap<String, Object>> list = CommonUtil.cast(dataMap.get("data"));
            webTableList.addAll(list);
        }
        webTableList.trimToSize();
        //将以上数据转换为我们自己的联行号数据并保存
        ArrayList<BankCode> bankCodeArrayList = new ArrayList<>(180000);
        for (LinkedTreeMap<String, Object> stringObjectLinkedTreeMap : webTableList) {
            try {
                BankCode bankCode = new BankCode();
                bankCode.setBankCode(stringObjectLinkedTreeMap.get("hanghao").toString());
                bankCode.setBankBranchName(stringObjectLinkedTreeMap.get("bankname").toString());
                //获取地区码和城市
                String areaId = stringObjectLinkedTreeMap.get("area_id").toString();
                City city = cityMap.get(areaId);
                if (!Objects.isNull(city)) {
                    bankCode.setAreaCode(city.getCityCode());
                    bankCode.setCity(city.getCityName());
                }
                //获取省
                String areaPid = stringObjectLinkedTreeMap.get("area_pid").toString();
                bankCode.setProvice(provinceMap.get(areaPid));
                bankCodeArrayList.add(bankCode);
            } catch (RuntimeException e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        }
        bankCodeArrayList.trimToSize();
        //保存
        saveBatch(bankCodeArrayList);
    }

    /**
     * 本方法仅限于generateBankInterbankNumber()使用其他地方请勿调用
     *
     * @return HashMap<省份ID, 省份名称>
     */
    private static HashMap<String, City> getCityMap() {
        String json = HttpService.doPost("http://lianhanghao.com/api/area/cityList", null);
        Map<String, Object> stringObjectMap = JsonUtil.jsonToObject(json, new TypeToken<Map<String, Object>>() {
        });
        ArrayList<LinkedTreeMap<String, Object>> list = CommonUtil.cast(stringObjectMap.get("data"));
        HashMap<String, City> cityMap = new HashMap<>();
        for (LinkedTreeMap<String, Object> map : list) {
            City city = new City();
            city.setCityName((String) map.get("name"));
            city.setCityCode((String) map.get("area_id"));
            city.setProvinceCode(map.get("pid").toString());
            cityMap.put(map.get("id").toString(), city);
        }
        return cityMap;
    }

    /**
     * 本方法仅限于generateBankInterbankNumber()使用其他地方请勿调用
     *
     * @return HashMap<省份ID, 省份名称>
     */
    private static HashMap<String, String> getProvinceMap() {
        HashMap<String, String> map = new HashMap<>();
        map.put("1", "北京市");
        map.put("2", "天津市");
        map.put("3", "河北省");
        map.put("4", "山西省");
        map.put("5", "内蒙古自治区");
        map.put("6", "辽宁省");
        map.put("7", "吉林省");
        map.put("8", "黑龙江省");
        map.put("9", "上海市");
        map.put("10", "江苏省");
        map.put("11", "浙江省");
        map.put("12", "安徽省");
        map.put("13", "福建省");
        map.put("14", "江西省");
        map.put("15", "山东省");
        map.put("16", "河南省");
        map.put("17", "湖北省");
        map.put("18", "湖南省");
        map.put("19", "广东省");
        map.put("20", "广西壮族自治区");
        map.put("21", "海南省");
        map.put("22", "四川省");
        map.put("23", "重庆市");
        map.put("24", "贵州省");
        map.put("25", "云南省");
        map.put("26", "西藏自治区");
        map.put("27", "陕西省");
        map.put("28", "甘肃省");
        map.put("29", "青海省");
        map.put("30", "宁夏回族自治区");
        map.put("31", "新疆维吾尔族自治区");
        map.put("32", "台湾");
        map.put("33", "香港");
        map.put("34", "澳门");
        return map;
    }
}
